package com.wenx.v3gateway.controller;

import com.wenx.v3gateway.starter.domain.RateLimitRule;
import com.wenx.v3gateway.starter.service.ConfigManagementService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 动态配置管理控制器
 * 提供限流规则和全局配置的动态管理接口
 * 
 * @author wenx
 */
@RestController
@RequestMapping("/api/v1/gateway/config")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "动态配置管理", description = "网关动态配置管理API")
public class DynamicConfigController {
    
    private final ConfigManagementService configManagementService;
    
    /**
     * 保存限流规则配置
     */
    @PostMapping("/rate-limit-rules")
    @Operation(summary = "保存限流规则", description = "保存限流规则到配置中心")
    public Mono<ResponseEntity<String>> saveRateLimitRules(@RequestBody List<RateLimitRule> rules) {
        log.info("Saving {} rate limit rules", rules.size());
        
        return configManagementService.saveRateLimitRules(rules)
            .then(Mono.fromCallable(() -> ResponseEntity.ok("Rate limit rules saved successfully")))
            .doOnSuccess(response -> log.info("Rate limit rules saved successfully"))
            .doOnError(error -> log.error("Failed to save rate limit rules", error));
    }
    
    /**
     * 保存全局配置
     */
    @PostMapping("/global-settings")
    @Operation(summary = "保存全局配置", description = "保存全局配置到配置中心")
    public Mono<ResponseEntity<String>> saveGlobalSettings(@RequestBody Map<String, Object> settings) {
        log.info("Saving global settings: {}", settings);
        
        return configManagementService.saveGlobalSettings(settings)
            .then(Mono.fromCallable(() -> ResponseEntity.ok("Global settings saved successfully")))
            .doOnSuccess(response -> log.info("Global settings saved successfully"))
            .doOnError(error -> log.error("Failed to save global settings", error));
    }
    
    /**
     * 获取配置版本
     */
    @GetMapping("/version")
    @Operation(summary = "获取配置版本", description = "获取当前配置版本号")
    public Mono<ResponseEntity<Map<String, String>>> getCurrentVersion() {
        return configManagementService.getCurrentVersion()
            .map(version -> ResponseEntity.ok(Map.of("version", version)));
    }
    
    /**
     * 强制刷新配置
     */
    @PostMapping("/refresh")
    @Operation(summary = "刷新配置", description = "强制刷新所有配置")
    public Mono<ResponseEntity<String>> forceRefreshConfig() {
        log.info("Force refreshing all configs");
        
        return configManagementService.forceRefreshConfig()
            .then(Mono.fromCallable(() -> ResponseEntity.ok("Configuration refreshed successfully")))
            .doOnSuccess(response -> log.info("Configuration refreshed successfully"))
            .doOnError(error -> log.error("Failed to refresh configuration", error));
    }
    
    /**
     * 健康检查
     */
    @GetMapping("/health")
    @Operation(summary = "健康检查", description = "检查动态配置服务健康状态")
    public Mono<ResponseEntity<Map<String, Object>>> health() {
        return configManagementService.getCurrentVersion()
            .map(version -> {
                Map<String, Object> response = new HashMap<>();
                response.put("status", "UP");
                response.put("service", "ConfigManagementService");
                response.put("version", version != null ? version : "unknown");
                response.put("timestamp", System.currentTimeMillis());
                return ResponseEntity.ok(response);
            })
            .onErrorReturn(createErrorResponse());
    }
    
    private ResponseEntity<Map<String, Object>> createErrorResponse() {
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("status", "DOWN");
        errorResponse.put("service", "ConfigManagementService");
        errorResponse.put("version", "unknown");
        errorResponse.put("error", "Failed to get version");
        errorResponse.put("timestamp", System.currentTimeMillis());
        return ResponseEntity.ok(errorResponse);
    }
}